package roboSoccer;

import java.awt.Color;
import java.awt.Graphics;
import java.text.DecimalFormat;

/**
 * Draws the field and objects, and also stores settings on how and what to
 * draw. There are many static final variables defining the dimensions of the
 * field. These comply with the RoboCup field dimensions, where every pixel is
 * one centimeter.
 * 
 * @author Ben Hopkins
 * 
 */
public class GraphicsUnit {

	// These are unchanging settings for drawing the field
	static final Color green = new Color(0, 120, 0); // the color of the field
	// Field dimensions : each centimeter is one pixel
	// These values are straight from 2009 rules.
	static final int totalX = 740;
	static final int totalY = 540;
	static final int fieldOffsetX = 67; // from far right edge to right field
										// edge
	static final int fieldOffsetY = 67; // same as above for height
	static final int fieldX = 605;
	static final int fieldY = 405;
	static final int goalY = 70;
	static final int goalX = 18;
	// the boxes for each goals consist of 90-degree arcs of the
	// radius of the box depth, boxX. Here, boxY is just referring
	// to the height of the straight part on the box.
	static final int boxX = 50;
	static final int boxY = 35;
	static final int circleR = 50; // center radius

	// display settings for other things on the screen
	static final int messageX = 200;
	static final int messageY = 490;
	static final int messageHeight = 12; // prints 12 point font

	/**
	 * Option to display labels on the robots, representing their behaviors.
	 */
	public boolean labelsFlag;
	/**
	 * Option to display additional info from the team's calculations.
	 */
	public boolean aiInfo;
	/**
	 * Option to draw all robots, as opposed to just the ones which are being updated and
	 * controlled.
	 */
	public boolean drawAll;

	/**
	 * Pointer to the game to draw.
	 */
	GameState game;

	/**
	 * Initializes variables, array of messages. By default all display options
	 * are on.
	 * 
	 * @param game
	 *            This is the GameState object which will be drawn.
	 */
	public GraphicsUnit() {
		labelsFlag = true;
		aiInfo = true;
		drawAll = true;

	}

	public void setGame(GameState game)
	{
		this.game = game;
	}
	
	/**
	 * Draws the field and field objects.
	 * 
	 * @param g
	 *            The graphics object which draws in the frame.
	 */
	public void draw(Graphics g) {
		// draw the green field background
		g.setColor(green);
		g.fillRect(0, 0, totalX, totalY);

		// draw the lines on the field
		g.setColor(Color.white);
		// boundry lines
		g.drawRect(fieldOffsetX, fieldOffsetY, fieldX, fieldY);
		// center line
		g.drawLine(fieldOffsetX + fieldX / 2, fieldOffsetY, fieldOffsetX
				+ fieldX / 2, fieldOffsetY + fieldY);
		// center circle
		g.drawArc(fieldOffsetX + fieldX / 2 - circleR, fieldOffsetY + fieldY
				/ 2 - circleR, circleR * 2, circleR * 2, 0, 360);
		// boxes
		// left box
		g.drawArc(fieldOffsetX - boxX, fieldOffsetY + fieldY / 2 - boxY / 2
				- boxX, boxX * 2, boxX * 2, 0, 90);
		g.drawArc(fieldOffsetX - boxX, fieldOffsetY + fieldY / 2 + boxY / 2
				- boxX, boxX * 2, boxX * 2, 270, 90);
		g.drawLine(fieldOffsetX + boxX, fieldOffsetY + fieldY / 2 - boxY / 2,
				fieldOffsetX + boxX, fieldOffsetY + fieldY / 2 + boxY / 2);
		// right box
		g.drawArc(fieldOffsetX + fieldX - boxX, fieldOffsetY + fieldY / 2
				- boxY / 2 - boxX, boxX * 2, boxX * 2, 90, 90);
		g.drawArc(fieldOffsetX + fieldX - boxX, fieldOffsetY + fieldY / 2
				+ boxY / 2 - boxX, boxX * 2, boxX * 2, 180, 90);
		g.drawLine(fieldOffsetX + fieldX - boxX, fieldOffsetY + fieldY / 2
				- boxY / 2, fieldOffsetX + fieldX - boxX, fieldOffsetY + fieldY
				/ 2 + boxY / 2);

		// goals
		g.setColor(Color.darkGray);
		g.drawRect(fieldOffsetX - goalX, fieldOffsetY + fieldY / 2 - goalY / 2,
				goalX, goalY);
		g.drawRect(fieldOffsetX + fieldX,
				fieldOffsetY + fieldY / 2 - goalY / 2, goalX, goalY);

		// draw the elements stored in the game
		if(game != null)
		{
		drawGame(g);
		drawTeams(g);
		drawRobots(g);
		drawBall(g);
		}

	}

	/**
	 * Draws any GameState messages/components.
	 * 
	 * @param g
	 *            The graphics object which draws.
	 */
	public void drawGame(Graphics g) {
		g.setColor(Color.white);
		g.drawString("Total frames: " + game.totalFrames, (int)GameState.leftQuarter.a.x, fieldOffsetY/3);
		
		if(game.sim != null)
		{
			g.drawString(Integer.toString(game.sim.score1), (int)GameState.leftEnd.center().x - 36, (int)GameState.leftEnd.center().y + 6);
			g.drawString(Integer.toString(game.sim.score2), (int)GameState.rightEnd.center().x + 30, (int)GameState.leftEnd.center().y + 6);
		}
	}

	/**
	 * Draws any RoboTeam information.
	 * 
	 * @param g
	 *            The graphics object which draws.
	 */
	public void drawTeams(Graphics g) {
		for (int j = 0; j < game.teams.length; j++) {
			RoboTeam t = game.teams[j];
			if (aiInfo) {
				if(t.teamNumber == 0)
					g.setColor(Color.pink);
				else
					g.setColor(Color.cyan);
				g.drawString("Team Behavior: " + t.teamBehavior, (int)(t.nearQuarter.a.x
						- GameState.topLine.b.x/8), (int)(fieldOffsetY*1.3 + fieldY));
				g.drawString("Players On Ball: " + t.onBall, (int)(t.nearQuarter.a.x
						- GameState.topLine.b.x/8), (int)(fieldOffsetY*1.3 + fieldY) + 12);
			}
		}
	}

	/**
	 * Draws any robots and their information.
	 * 
	 * @param g
	 *            The graphics object which draws.
	 */
	public void drawRobots(Graphics g) {
		for (int j = 0; j < game.teams.length; j++)
			for (int i = 0; i < game.teams[j].players.length; i++) {
				RoboPlayer r = game.teams[j].players[i];
				if( drawAll || (r.controller.functioning && r.position.x > 0))
				{
				if (r.team.teamNumber == 0)
					g.setColor(Color.red);
				else
					g.setColor(Color.blue);
				g.fillArc((int) r.position.x - RoboPlayer.sizeRadius,
						(int) r.position.y - RoboPlayer.sizeRadius,
						RoboPlayer.sizeRadius * 2, RoboPlayer.sizeRadius * 2,
						0, 360);
				g.setColor(Color.white);
				g.fillArc((int) r.position.x - RoboPlayer.sizeRadius,
						(int) r.position.y - RoboPlayer.sizeRadius,
						RoboPlayer.sizeRadius * 2, RoboPlayer.sizeRadius * 2,
						(int) r.position.direction - RoboPlayer.drawDirWidth
								/ 2, RoboPlayer.drawDirWidth);

				if (labelsFlag) {
					g.drawString(r.id + ":" + r.behavior, (int) r.position.x + RoboPlayer.sizeRadius,
							(int) r.position.y + RoboPlayer.sizeRadius);
					g.drawString(r.behavior.message, (int) r.position.x + RoboPlayer.sizeRadius,
							(int) r.position.y + RoboPlayer.sizeRadius + 12);
				}
				}
			}
	}

	/**
	 * Draws the ball.
	 * 
	 * @param g
	 *            The graphics object which draws.
	 */
	public void drawBall(Graphics g) {
		FieldObject b = game.ball;
		g.setColor(Color.orange);
		g.fillArc((int) b.position.x - FieldObject.sizeRadius,
				(int) b.position.y - FieldObject.sizeRadius,
				FieldObject.sizeRadius * 2, FieldObject.sizeRadius * 2, 0, 360);

		// Show the position of the ball a number of steps into the future
		if (labelsFlag) {
			g.setColor(Color.cyan);
			Vector r = b.futurePosition(100);
			g.fillArc((int) r.x - FieldObject.sizeRadius, (int) r.y
					- FieldObject.sizeRadius, FieldObject.sizeRadius * 2,
					FieldObject.sizeRadius * 2, 0, 360);
			DecimalFormat dc = new DecimalFormat("####.#");
			g.drawString(dc.format(b.velocity.x) + ", "
					+ dc.format(b.velocity.y), (int) b.position.x + 10,
					(int) b.position.y + 10);
		}
	}
}
